package pers.spj.image.analysis

import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.util.PsiUtilBase
import pers.spj.image.analysis.iface.OnCancelListener
import pers.spj.image.analysis.iface.OnConfirmListener
import pers.spj.image.analysis.ui.AnalysisResultEntry
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.SwingUtilities
import javax.swing.WindowConstants

/**
 * @author supeijin
 * @date 2019/4/22.
 */
class AnalysisAction : AnAction {
    constructor() {
    }

    override fun update(e: AnActionEvent) {
        super.update(e)
        val presentation = e.presentation
        val virtualFile : VirtualFile?= getVirtualFile(e);
        if(virtualFile==null){
            presentation.isEnabledAndVisible=false;
        }else{
            presentation.isEnabledAndVisible = virtualFile.isDirectory || IMAGE_TYPE == virtualFile.fileType.name;
        }
    }

    override fun actionPerformed(event: AnActionEvent) {
        ApplicationManager.getApplication().runReadAction {
            val virtualFile: VirtualFile? = getVirtualFile(event);
            val project: Project? = getProject(event);
            if (virtualFile != null && project != null) {
                val unusedImages = getUnusedImages(project, virtualFile);
                processingResult(project,unusedImages);
            }
        }
    }
    private fun processingResult(project: Project,unusedImages:List<VirtualFile> ){
        SwingUtilities.invokeLater {
            if (unusedImages.isEmpty()) {
                Messages.showInfoMessage(project, "Nothing was found", "tips")
            } else {
                val resultEntry = AnalysisResultEntry(unusedImages);
                val dialog = getDefaultDialog(resultEntry);
                resultEntry.setOnCancelListener(object : OnCancelListener {
                    override fun onCancel() {
                        dialog.isVisible = false;
                    }
                })
                resultEntry.setOnConfirmListener(object : OnConfirmListener<MutableList<VirtualFile>> {
                    override fun onConfirm(fileList: MutableList<VirtualFile>) {
                        dialog.isVisible = false;
                        //删除当前文件
                        WriteCommandAction.runWriteCommandAction(project) {
                            for (file in fileList) {
                                val psiFile = PsiUtilBase.getPsiFile(project, file)
                                psiFile.delete()//删除文件
                            }
                        }
                    }
                })
            }
        }
    }
    private fun getProject(event: AnActionEvent): Project? {
        val project = event.getData(PlatformDataKeys.PROJECT);
        return project;
    }

    private fun getVirtualFile(event: AnActionEvent): VirtualFile? {
        return event.getData(PlatformDataKeys.VIRTUAL_FILE);
    }

    private fun getDefaultDialog(jPanel: JPanel): JFrame {
        val dialog = JFrame()
        dialog.add(jPanel)
        dialog.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
        dialog.pack()
        dialog.setLocationRelativeTo(null)
        dialog.isVisible = true
        return dialog
    }

    /**
     * 获取项目中未使用的图片文件
     */
    private fun getUnusedImages(project: Project, virtualFile: VirtualFile): List<VirtualFile> {
        val imagesFiles: List<VirtualFile> = getImagesFiles(virtualFile);//原生图片
        if(imagesFiles.isEmpty()){
            return imagesFiles;
        }else {
            val targetFiles: List<VirtualFile> = getModuleTargetFiles(project, virtualFile);
            val referenceImages: List<VirtualFile> = getReferenceImages(project, imagesFiles, targetFiles);//被引用的图片
            return when {
                referenceImages.isEmpty() -> imagesFiles
                else -> {
                    val unusedImages = ArrayList<VirtualFile>();
                    for (sourecImage in imagesFiles) {
                        if(!containFile(referenceImages,sourecImage)){
                            unusedImages.add(sourecImage);
                        }
                    }
                    unusedImages;
                }
            }
        }
    }
    //判断文件列表中是否包含当前文件
    private fun containFile(fileList:List<VirtualFile>, file:VirtualFile):Boolean{
        for (itemFile in fileList) {
            if (itemFile == file) {
                return true;
            }
        }
        return false;
    }
    /**
     * 获取当前目录下所有的图片资源
     */
    private fun getImagesFiles(virtualFile: VirtualFile): List<VirtualFile> {
        val fileList = ArrayList<VirtualFile>();
        if (virtualFile.isDirectory) {
            val virtualFiles = virtualFile.children//选中目录下的文件（图片文件）
            if (virtualFiles.isNotEmpty()) {
                for (file in virtualFiles) {
                    if (IMAGE_TYPE == file.fileType.name) {
                        fileList.add(file);
                    } else if (file.isDirectory) {
                        fileList.addAll(getImagesFiles(file));
                    }
                }
            }
        } else if (IMAGE_TYPE == virtualFile.fileType.name) {
            fileList.add(virtualFile);
        }
        return fileList
    }

    /**
     * 获取除图片外的文件
     */
    private fun getScanningFile(virtualFile: VirtualFile): List<VirtualFile> {
        val files = ArrayList<VirtualFile>()
        if (IDEA_TYPE != virtualFile.name && GIT_TYPE != virtualFile.name) {
            if (virtualFile.isDirectory && IGNORE_FOLDS.indexOf(virtualFile.name)<0) {
                val virtualFiles = virtualFile.children
                for (file in virtualFiles) {
                    files.addAll(getScanningFile(file))
                }
            } else {
                val fileTypeName = virtualFile.fileType.name;
                if (SUPPORT_FILES.indexOf(fileTypeName)>=0) {
                    files.add(virtualFile);
                }else{
                    println("virtualFile.name=== "+virtualFile.name +"  fileTypeName == $fileTypeName")
                }
            }
        }
        return files
    }

    /**
     * 获取当前项目下的所有文件
     */
    private fun getModuleTargetFiles(project: Project, virtualFile: VirtualFile): List<VirtualFile> {
        val projectBasePath: String = project.basePath.toString();
        return when (val projectBasePathVirtualFile: VirtualFile? = virtualFile.fileSystem.findFileByPath(projectBasePath)) {
            null -> emptyList()
            else -> getScanningFile(projectBasePathVirtualFile)//目标文件
        }
    }

    /**
     * 获取所有的引用的图片文件
     */
    private fun getReferenceImages(project: Project, resourceImages: List<VirtualFile>, files: List<VirtualFile>): List<VirtualFile> {
        val size = resourceImages.size;
        if (size == 0) {
            return emptyList();
        } else {
            var referenceList = ArrayList<VirtualFile>();
            for (imageFile in resourceImages) {
                val fileName: String = imageFile.name;
                for (sourceFile in files) {
                    if(sourceFile.name.indexOf(".")>0){
                        val psiFile = PsiUtilBase.getPsiFile(project, sourceFile);
                        val fileText = psiFile.text;
                        if (fileText.indexOf(fileName) >= 0) {
                            referenceList.add(imageFile);
                            break;
                        }
                    }
                }
            }
            return referenceList;
        }
    }
    companion object {
        private const val IMAGE_TYPE: String = "Image";
        private const val IDEA_TYPE: String = ".idea";
        private const val GIT_TYPE: String = ".git";
        private const val SVN: String = ".svn";
        private const val NODE_MODULES: String = "node_modules";//库文件
        private const val DS_STORE: String = ".DS_Store";
        private const val FOLD_1: String = "*~";
        private const val PYCACHE: String = ";__pycache__";
        private const val XML: String = "XML";
        private const val HTML: String = "HTML";
        private const val JSON: String = "JSON";
        private const val VUE: String = "Vue.js";
        private const val CSS: String = "CSS";
        private const val LESS: String = "Less";
        private const val PLAIN_TEXT: String = "PLAIN_TEXT";
        private const val JAVA_SCRIPT: String = "JavaScript";
        val SUPPORT_FILES: List<String> = listOf(XML, HTML, JAVA_SCRIPT, JSON,VUE,CSS,LESS,PLAIN_TEXT);
        val IGNORE_FOLDS:  List<String> = listOf(IDEA_TYPE,GIT_TYPE,SVN,NODE_MODULES,DS_STORE,FOLD_1,PYCACHE);
        val IGNORE_FILES:  List<String> = listOf(".hprof",".pyc",".pyo",".rbc",".yarb");
    }
}